home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / cpp / typecase.c < prev   
C/C++ Source or Header  |  1992-04-13  |  5KB  |  205 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *
  16.  * Created: MJF 08/20/90 -- Initial design and implementation.
  17.  *
  18.  * The TYPE_CASE defmacro
  19.  *
  20.  * To use, declare:
  21.  *     #pragma defmacro TYPE_CASE "type_case" delimiter=}
  22.  *
  23.  * TYPECASE (generic_ptr) { case_statements }
  24.  * case_statements = case sym_name : statements [case_statements]
  25.  * 
  26.  * THE TYPE_CASE macro is analogous to the C++ switch statment 
  27.  * It gathers all possible cases and allows the user to symbolically 
  28.  * dispatch on the type  of object  represented  by  the case statements.
  29.  *
  30.  *     Generic* g;
  31.  *     TYPE_CASE (g) {
  32.  *       case Vector:                // If the object is a vector
  33.  *         ....                      // Do something for Vector
  34.  *         break;
  35.  *       case List:                  // If the object is a list
  36.  *         ....                      // Do something for List
  37.  *         break;
  38.  *       default:                    // Else do the rest
  39.  *          ....
  40.  *     }
  41.  *
  42.  * expands to:
  43.  *
  44.  *     Generic* g;
  45.  *     static Symbol* switch_symbols_g[3] = {SYM(Vector), SYM(List), NULL};
  46.  *     switch (g->select_type_of(switch_symbols_g)) {
  47.  *       case 0:                     // If the object is a vector
  48.  *         ....                      // Do something for Vector
  49.  *         break;
  50.  *       case 1:                     // If the object is a list
  51.  *         ....                      // Do something for List
  52.  *         break;
  53.  *       default:                    // Else do the rest
  54.  *          ....
  55.  *     }
  56.  *   
  57. */
  58.  
  59. #include "defmacio.h"
  60.  
  61. #define MAXCASE  64
  62. #define MAXBUF   512
  63.  
  64. typedef struct case_body {
  65.   int default_case;
  66.   char* body;
  67. } Case_Body;
  68.  
  69.  
  70. typecase(argc, argv)
  71.  int argc;
  72.  char* argv[];
  73. {
  74.   char junk[MAXBUF];
  75.   char c;
  76.   char* macname;        /* TYPE_CASE is the macro name */
  77.   char* genptr;            /* the name of a generic pointer */
  78.   char* name;
  79.   char *str1, *str2;
  80.   Case_Body  cbody[30];
  81.   int ncases, i;
  82.   char* syms[30];        /* Contains all symbols in TYPE_CASE */
  83.   int nsyms;
  84.   char body[512];        /* Contains body of each case  */
  85.   int done;
  86.  
  87.   if(copytoken(junk) == NULL)    /* Skip macro name */
  88.     return(1);
  89.   macname = savestring(junk);
  90.  
  91.   c = skip_blanks();
  92.   if(c != '(') {
  93.     fprintf(stderr, "%s: '%c' found instead of '('\n", macname, c);
  94.     return 1;
  95.   }
  96.  
  97.   done = 0;
  98.   nsyms = ncases = 0;
  99.   name = scan_next(' ');
  100.   c = getchar();
  101.   if (c != ')') {
  102.     fprintf(stderr, "%s: '%c' found instead of ')' after %s\n", 
  103.         macname, c,  name);
  104.     return 1;
  105.   }
  106.   genptr = savestring(name);
  107.  
  108.   c = skip_blanks();
  109.   if (c != '{') {
  110.     fprintf(stderr, "%s: '%c' found instead of '{' after %s\n", 
  111.         macname, c,  genptr);
  112.     return 1;
  113.   }
  114.  
  115.   name = scan_list(' ');
  116.  
  117.   for (i=0;i< MAXCASE;i++) {
  118.     str2 = body;
  119.     if (name == NULL) return 1;
  120.  
  121.  
  122.     if(!strcmp(name, "case")) {          /* case Vector: */
  123.       cbody[i].default_case = 0;
  124.       cbody[i].body = 0;
  125.       name = scan_next(' ');
  126.       c = skip_blanks();
  127.       if (c != ':') {
  128.     fprintf(stderr, "%s: Missing ':' after '%s'\n", 
  129.         macname, name);
  130.     return 1;
  131.       }
  132.       syms[nsyms++] = savestring(name);
  133.     } else if (!strcmp(name, "default")) { /* default: */
  134.       c = getchar();
  135.       if (c != ':') {
  136.     fprintf(stderr, "%s: Missing ':' after '%s'\n", 
  137.         macname, name);
  138.     return 1;
  139.       }
  140.       cbody[i].default_case = 1;
  141.       cbody[i].body = 0;
  142.     } else  {
  143.       str1 = name;
  144.       while (*str1 != '\0')  *str2++ = *str1++;
  145.     }
  146.  
  147.     /* collect body of case */
  148.     for (;;) {
  149.       c = getchar();
  150.       while (!isalnum(c) && c !=EOF) {
  151.     *str2++ = c;
  152.     c = getchar();
  153.       }
  154.       if (c == EOF) {              /* TYPE_CASE is done */
  155.     done = 1;
  156.     break;
  157.       } else unget();
  158.       
  159.       name = scan_list(' ');
  160.       if (!strcmp(name,"case") || !strcmp(name,"default")) break;
  161.       
  162.       str1 = name;
  163.       while (*str1 != '\0') *str2++ = *str1++;
  164.     }
  165.     ncases++;
  166.    *str2 = EOS;
  167.     cbody[i].body = savestring(body);
  168.     if (done) break;
  169.   }
  170.  
  171.   /* expand TYPE_CASE macro*/
  172.  
  173.   sprintf(junk, "\n{\nstatic Symbol* switch_symbols_%s[%d] = {", 
  174.       genptr, nsyms+1);
  175.   puts(junk);                  /* start of SYM list */
  176.   for (i = 0; i < nsyms; i++) {          /* output each SYM name */
  177.       sprintf(junk,"SYM(%s),", syms[i]);
  178.       puts(junk);
  179.   }
  180.   puts("NULL};\n");              /* end of SYM list */
  181.   
  182.   sprintf(junk, "switch(%s->select_type_of(switch_symbols_%s)) {\n",
  183.       genptr, genptr);
  184.   puts(junk);                  /* start of switch statement */
  185.  
  186.  
  187.  
  188.   for (i = 0; i< ncases; i++) {          /* output body for each case */
  189.     if (cbody[i].default_case)
  190.      sprintf(junk, "default:", i);
  191.     else
  192.      sprintf(junk, "case %d:", i);
  193.     puts(junk);
  194.     if (cbody[i].body)
  195.       puts(cbody[i].body);
  196.   }
  197.   puts ("\n} \n");              /* end of switch statement */
  198.   free(macname);
  199.   return 0;
  200. }
  201.  
  202.  
  203.  
  204.  
  205.